param(
	[Parameter(Mandatory=$False)]
	[string]$inputFile="inputlist.txt",						  # the input file to store vdi and fid list
	[string]$checkListFile="to_be_checked_file_list.txt",     # the input file to store file list that will be checked
	[switch]$inputFileSaved                                   # if inputlist.txt has been saved, if yes, it will run directly
)
If( $env:username -inotmatch 'aaadmin' ){
    [void][System.Windows.Forms.MessageBox]::Show('Please only run me in aaadmin user session', 'Authentication Error', 'OK', 'Error')
    exit
}
Function Start-BulkThreads(){	# -Action { Stop-Process -Id $PID }
    param(
    	[Parameter(Mandatory=$True)]
    	[Object]$vdilist,               # the vdi list that scripts to be ran
    	[Parameter(Mandatory=$True)]    
    	[ScriptBlock]$Action,           # the actual action that each thread will run
    	[AllowNull()]
    	[Object[]]$ActionParams,
        [Parameter(Mandatory=$false)]   
    	[int]$maxCnt=100                # the default amount of powershell threads, if this number is big, then the system might get stuck
    )
	$results=@() # this is used to collect the result from each thread
	$vdiCounts = $vdilist.Count
	If( $vdiCounts -eq 1 ){ # no need to create thread pool to run it
		If( [string]::IsNullOrWhiteSpace($vdilist[0]) ){
		    write-error "vdilist only contains 1 line but it's null"
		}else{& $Action $vdilist[0] 1 $ActionParams}
	}else{
		$vdiCounts = $vdilist.Count ; $throttleLimit=$maxCnt ; If($vdiCounts -le $maxCnt ){$throttleLimit=$vdiCounts}
		# creaate the thread pool and run each thread based the vdi list amount
		$SessionState = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
		$Pool = [runspacefactory]::CreateRunspacePool(1, $throttleLimit, $SessionState, $Host)
		$Pool.Open() ; $threads = @() ; $cnt=1
		$handles = foreach($line in $vdilist){
			if( [string]::IsNullOrWhiteSpace($line ) ){continue}
			$powershell = [powershell]::Create().AddScript($Action).AddArgument($line).AddArgument($cnt).AddArgument($ActionParams)
			$powershell.RunspacePool = $Pool ;	$powershell.BeginInvoke() ; $threads += $powershell ; $cnt++
		}
		# wait each thread to be done and then collecte its return value
		do{
		  $i = 0 ;  $done = $true
		  foreach ($handle in $handles) {
			if($handle -ne $null){if($handle.IsCompleted){$results+=$threads[$i].EndInvoke($handle);$threads[$i].Dispose();$handles[$i]=$null}else{$done = $false}}
			$i++
		  }
		  if (-not $done) { Start-Sleep -Milliseconds 200 }
		} until ($done)
	}
	return $results # return the value collection from each thread and then export to csv or take other further actions
}
$this_path = Split-Path -Parent ($MyInvocation.MyCommand.Definition)
$this_user=$env:username
$this_machine=$env:computername
$inputlist=$null
#<-------------------------------- open inputlist.txt(create it if it not exists) and let user to enter the vdi list.
$inputFile="$this_path\$inputFile" ; If(!(test-path $inputFile )){new-item -ItemType File -Path $inputFile -force 1>$null}
$checkListFile="$this_path\$checkListFile" ; If(!(test-path $checkListFile )){new-item -ItemType File -Path $checkListFile -force 1>$null}
$inputlist = get-content $inputFile |select -Unique|?{$_.trim() -ne ""}|sort
If( ($PSBoundParameters.ContainsKey('inputFileSaved') -and $inputlist.count -eq 0) -or !$inputFileSaved ){
	clear-content $inputFile -force -ErrorAction Ignore
	Do{ # loop above action if the vdi list is empty 
		write-host "Please save vdi(fid) list as below format in opened txt file each line as it's empty, please press 'Ctrl+C' if you want to quit:
		
        MWDINTVM123296,aas0009
        MWDINTVM123297,aas0010"; notepad $inputFile; read-host " "
		# get unique vdi name (exclude empty/blank spaces line)
		$inputlist = (get-content $inputFile |select -Unique|?{$_.trim() -ne ""}|sort)
	}While( $inputlist -eq $null  )
}
$file_list=get-content $checkListFile |select -Unique|?{$_.trim() -ne ""}|sort
If( ($PSBoundParameters.ContainsKey('inputFileSaved') -and $file_list.count -eq 0) -or !$inputFileSaved ){
	clear-content $checkListFile -force -ErrorAction Ignore
	Do{ # loop above action if the vdi list is empty 
		write-host "Please save file list as below format in opened txt file each line as it's empty, 
        if the path contains fid, please replace it with '#fid' like below example,
        please press 'Ctrl+C' if you want to quit:
        
		C$\Program Files (x86)\Automation Anywhere Enterprise 10.3\Client\AAPlayer.exe
        C$\Users\#fid\Documents\Automation Anywhere Files\AA.Settings.xml" 
        notepad $checkListFile; read-host " "
		# get unique vdi name (exclude empty/blank spaces line)
		$file_list = (get-content $checkListFile |select -Unique|?{$_.trim() -ne ""}|sort)
	}While( $file_list -eq $null  )
}
$merge_list=@()
Foreach( $vdi in $inputlist){
    Foreach( $file in $file_list){
        $merge_list+="$vdi,$file"
    }
}
$file_check_action={
    param($line,$cnt)
	$vdi,$fid,$file_path=$line.split(",")
    $file_path="\\$vdi\$file_path".replace(':','$').replace('#fid',"$fid")
    $file_result=''|select @{n="VDI";e={$vdi }},@{n="FID";e={$fid }},@{n="File";e={$file_path }},@{n="LastWriteTime";e={'' }},@{n="CheckSum";e={'' }}
	write-host "Processing in $cnt --> $file_path`n"
    If(Test-Connection $vdi -quiet -count 1 -ea 0){
		Try{
            If( test-path $file_path -ea 1){
                $lwt="{0:MM/dd/yyyy HH:mm:ss}" -f (gi $file_path).LastWriteTime
                $cs=(Get-FileHash $file_path -Algorithm MD5 -ea 0).hash
            }else{
                $lwt='File Not Exists' ; $cs='N/A'
            }
		}Catch{
		   $lwt=$_.exception ; $cs='N/A'
		}Finally{}
	}else{
	    $lwt="$vdi is offline or invalid vdi name" ; $cs='N/A'
	}
    $file_result.LastWriteTime=$lwt
    $file_result.CheckSum=$cs
    return $file_result
}
$rst=Start-BulkThreads $merge_list $file_check_action
$rst|Export-Csv -Path "$this_path\file_property.csv" -UseCulture -NoTypeInformation -Encoding UTF8 -Force -ErrorAction Ignore
write-host -ForegroundColor Yellow "File property in each VDI has been saved in '$this_path\file_property.csv'(you can close this window now)"
